/*
 * Copyright 2024 ywcai
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

`include "defines.v"
`timescale 1ns/1ps

module mem_wb(
	input	wire				clk,
	input	wire				rst_n,

	input	wire[`MemAddrBus]	pc_i,
	input	wire				regwrite_en_i,
	input	wire[`RegAddrBus]	regwrite_addr_i,
	input	wire[`RegDataBus]	mem_read_data_i,
	input	wire[`RegDataBus]	ex_result_i,
	input	wire[`MemAddrBus]	pc_target_i,
	input	wire[`RegDataBus]	csr_rd_data_i,

	input	wire[2:0]			mux_result_src_i,

	output	reg                 regwrite_en_o,
	output	reg[`RegAddrBus]	regwrite_addr_o,
	output	reg[`RegDataBus]	regwrite_data_o
    );

	wire[`MemAddrBus] pc_subseq = pc_i + 4;

	wire[`RegDataBus] regwrite_data =
        ({`XLEN{mux_result_src_i == 3'b000}} & ex_result_i)
		| ({`XLEN{mux_result_src_i == 3'b001}} & mem_read_data_i)
		| ({`XLEN{mux_result_src_i == 3'b010}} & {24'h0, pc_subseq})
		| ({`XLEN{mux_result_src_i == 3'b011}} & {24'h0, pc_target_i})
		| ({`XLEN{mux_result_src_i == 3'b100}} & csr_rd_data_i);

	always @(posedge clk) begin
		if (rst_n == `RESET_ENABLE) begin
			regwrite_en_o <= `DISABLE;
			regwrite_addr_o <= `REG_ZERO_ADDR;
			regwrite_data_o <= `ZERO;
		end else begin
			regwrite_en_o <= regwrite_en_i;
			regwrite_addr_o <= regwrite_addr_i;
			regwrite_data_o <= regwrite_data;
		end
	end

endmodule
